package com.hissy.common.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;

/**
 * Freemarker模板工具类
 *
 * @author zhangyanfei
 */
public class FreemarkerUtil {

    /**
     * 模版配置对象
     */
    private static final Configuration cfg;

    static {

        cfg = new Configuration();

        try {
            //三者选一，另外两个注释
            one_dir1();//一个文件夹路径
            //one_dir2();//一个文件夹路径
            //more_dir();//多个文件夹路径

        } catch (IOException e) {
            e.printStackTrace();
        }

        // 设置默认编码
        cfg.setDefaultEncoding("utf-8");

        //错误控制器，控制异常，详情看图4
        //RETHROW_HANDLER ：错误信息会输出到控制台
        //HTML_DEBUG_HANDLER : 错误信息会输出到你要生成的html页面，详情看图4_1
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        //cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
    }

    /**
     * 所有模板都在一个文件夹路径，详情看 图1 或 图2
     */
    private static void one_dir1() throws IOException {
        cfg.setDirectoryForTemplateLoading(new File("/Users/zhangyanfei/workspace/hissy-common/src/main/resources"
            + "/template"));
    }

    /**
     * 所有模板都在一个文件夹路径，详情看 图2
     */
    private static void one_dir2() throws IOException {
        //ftl模板文件统一放至 com.testExample.freemarker.template 包下面
        cfg.setClassForTemplateLoading(FreemarkerUtil.class, "template/");
    }

    /**
     * 所有模板分别在多个文件夹路径，详情看 图3
     */
    private static void more_dir() throws IOException {
        //建议，就算不同文件夹，但是模板文件名也不能相同，详情看 图3
        FileTemplateLoader ftl1 = new FileTemplateLoader(new File("C:/freemarker_ftl"));
        FileTemplateLoader ftl2 = new FileTemplateLoader(new File("E:/freemarker_ftl"));
        ClassTemplateLoader ctl = new ClassTemplateLoader(FreemarkerUtil.class,
            "/com/testExample/freemarker/template/");
        TemplateLoader[] loaders = new TemplateLoader[] {ftl1, ftl2, ctl};
        MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);

        cfg.setTemplateLoader(mtl);
    }

    private void process(String templateName, String targetFileName, Map<String, Object> root) throws Exception {
        Writer out = null;
        try {
            File file = new File(targetFileName);
            if (!file.exists()) {
                file.createNewFile();
                //因为是生成到 Linux 上，需要设置权限，自己写的
                //设置可执行权限，第二个参数默认为true（表示root权限才可以执行该文件，false为所有人都可以）
                file.setExecutable(true, false);
                //设置可读权限，第二个参数默认为true（同上）
                file.setReadable(true, false);
                //设置可写权限，第二个参数默认为true（这里可以省略不写）
                file.setWritable(true);
            }

            //创建模版对象，详情看 图5
            Template t = cfg.getTemplate(templateName);

            //设置输出流，详情看 图6
            //out = new OutputStreamWriter(System.out); //-> 输出到控制台
            //设置编码  UTF-8
            out = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");

            //在模版上执行插值操作，并输出到制定的输出流中，详情看 图5
            //root 是模板ftl中的变量的值
            t.process(root, out);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != out) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 从模板生成静态html页面
     *
     * @param templateName   模板文件名
     * @param targetFileName 目标文件名，即 html 的文件名，包含路径，绝对路径
     * @param root           模板里面变量的值
     */
    public static void generatorHtmlFromTemplate(String templateName, String targetFileName, Map<String, Object> root) {
        FreemarkerUtil hf = new FreemarkerUtil();
        try {
            hf.process(templateName, targetFileName, root);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        Map<String, Object> root = new HashMap<>();
        root.put("username", "美女");
        root.put("age", 18);
        root.put("sex", "男");

        FreemarkerUtil.generatorHtmlFromTemplate("test.ftl", "abc.html", root);
    }
}